/**
* ...
* @author Default
* @version 0.1
*/

package  
{

	import flash.geom.*;
	import Camera3D;
	
	public class Object3D
	{
		
		public var vertices:Array;
		
		public var x:Number;
		public var y:Number;
		public var z:Number;
		public var visible:Boolean = true;
		
		private var center : Vertex;
		private var v : Vertex;
		
		private var sx : Number 
		private var cx : Number 
		private var sy : Number 
		private var cy : Number 
		private var sz : Number 
		private var cz : Number 
		
		
		private	var xy : Number;
		private var xz : Number;
			
		private var yx : Number;
		private var yz : Number;
			
		private var zx : Number;
		private var zy : Number;
			

		public var WIDTH : Number;
		public var HEIGHT : Number;
		public var LENGTH : Number;
		
		public var DEPTH : Number;
		
		public var rotationX:Number;
		public var rotationY:Number;
		public var rotationZ:Number;
		
		
		
		public function Object3D( X:Number = 0, Y:Number = 0, Z:Number = 0 ) 
		{
			
			vertices = [];
			x = X;
			y = Y;
			z = Z;
			rotationX = rotationY = rotationZ = 0;
			
		}
		
		 
		public function update( array:Array = null ):void
		{
			
			var x : Number;
			var y : Number;
			var z : Number;
			
			var ratio : Number;
			
			sx = Math.sin( rotationX );
			cx = Math.cos( rotationX );
			
			sy = Math.sin( rotationY );
			cy = Math.cos( rotationY );
			
			sz = Math.sin( rotationZ );
			cz = Math.cos( rotationZ );
			
			DEPTH = 0;
			
			//allows the rendering of a given array passed as an argument to the function
			var list:Array = ( array == null ) ? vertices : array;
			
			//visibility = 0;
			visible = false;
			
			var i:int = list.length;
			while (i--)
			{
				
				v = list[ i ];
				
				// assign variables for the current x, y and z
				x = this.x + v.x;
				y = this.y + v.y;
				z = this.z + v.z;
				/*
				x = Scene3D.origin.x - this.x + v.x// - Scene3D.camera.x;
				y = Scene3D.origin.y - this.y + v.y// - Scene3D.camera.y;
				z = Scene3D.origin.z - this.z + v.z// - Scene3D.camera.z;
				*/
				
				// rotation around x
				xy = cx * y - sx * z;
				xz = sx * y + cx * z;
				
				// rotation around y
				yz = cy * xz - sy * x;
				yx = sy * xz + cy * x;
				
				// rotation around z
				zx = cz * yx - sz * xy;
				zy = sz * yx + cz * xy;
				
				ratio = Scene3D.focalLength / ( Scene3D.focalLength + Scene3D.camera.z + yz );
			
				
				//rendu ecran
				v.screenX = Scene3D.camera.x + zx * ratio;
				v.screenY = Scene3D.camera.y + zy * ratio;
				
				if( Scene3D.camera.viewport.contains( v.screenX, v.screenY ) ) visible=true;
				
				v.depth = yz;
				DEPTH += yz;
				
			}
			
			DEPTH /= 3;
			
			
		}
		
		public function getGravityCenter():void 
		{
			
			var x:Number;
			var y:Number;
			var z:Number;
			
			var xmin:Number;
			var xmax:Number;
			var ymin:Number;
			var ymax:Number;
			var zmin:Number;
			var zmax:Number;
			
			vertices.sortOn( 'x', Array.DESCENDING | Array.NUMERIC );
			xmin = vertices[ 0 ].x;
			xmax = vertices[ vertices.length - 1 ].x;
			x = xmin + ( xmax - xmin ) / 2;
			
			vertices.sortOn( 'y', Array.DESCENDING | Array.NUMERIC );
			ymin = vertices[ 0 ].y;
			ymax = vertices[ vertices.length - 1 ].y;
			y = ymin + ( ymax - ymin ) / 2;
			
			vertices.sortOn( 'z', Array.DESCENDING | Array.NUMERIC );
			zmin = vertices[ 0 ].z;
			zmax = vertices[ vertices.length - 1 ].z;
			z = zmin + ( zmax - zmin ) / 2;
			
			WIDTH = Math.abs( xmax - xmin );
			HEIGHT = Math.abs( ymax - ymin );
			LENGTH = Math.abs( zmax - zmin );
			
		}
		
		public function boundingBox():Array
		{
			
			getGravityCenter();
			
			var w:Number = WIDTH;
			var h:Number = HEIGHT;
			var l:Number = LENGTH;

			var col:uint = 0xFFFFFFFF;
			
			var bbPoints:Array = [];
			
			bbPoints.push(
			
				new Vertex(-w/2, -h/2, -l/2, col), 
				new Vertex( w/2, -h/2, -l/2, col), 
				new Vertex( w/2, -h/2,  l/2, col), 
				new Vertex(-w/2, -h/2,  l/2, col), 
				new Vertex(-w/2,  h/2, -l/2, col), 
				new Vertex( w/2,  h/2, -l/2, col), 
				new Vertex( w/2,  h/2,  l/2, col), 
				new Vertex(-w/2,  h/2,  l/2, col)
				
			);
			return bbPoints;
			
		}
		
		public function centerModel():void
		{	
			
			getGravityCenter();
			translate( -WIDTH/2, -HEIGHT/2, -LENGTH/2 );
			
		}
		
		public function translate( x:Number, y:Number, z:Number ):void
		{
			
			var v:Vertex;
			var i:int;
			for ( i = 0; i < vertices.length; i++ )
			{
				
				v = vertices[i];
				v.x += x;
				v.y += y;
				v.z += z;
				
			}
			
		}
		
		public function rotate( x:Number, y:Number, z:Number ):void
		{
			
			rotationX = x;
			rotationY = y;
			rotationZ = z;
			
			
			
		}
		
		public function scale( x:Number, y:Number = NaN, z:Number = NaN ):void
		{
			
			if( isNaN( y) ) y = x;
			if( isNaN( z )) z = x;
			
			var v:Vertex;
			var i:int;
			
			var min:Number = Number.MIN_VALUE;
			var max:Number = Number.MAX_VALUE;
			
			for ( i = 0; i < vertices.length; i++ )
			{
				
				v = vertices[i];
				v.x *= x;
				v.y *= y;
				v.z *= z;
				
			}
		//	update();
		}
	
	}
	
}
